package view;

import entity.Cell;
import entity.Point;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.Vector;
import model.Arena;
import model.Robot;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author minhtue001
 */
public class Drawer {
    private static final Drawer drawer = new Drawer();
    private static final int X0 = 20;
    private static final int Y0 = 20;
    private static final int CELL_SIZE = 28;
    private static final int ROBOT_SIZE = CELL_SIZE * 2;
    private static final int CELL_ALIGN = 4;
    
    private Vector<Cell> emptyPlottedCells;
    
    private Arena arena;
    private Robot robot;
    
    private Graphics2D g;

    public Arena getArena() {
        return arena;
    }

    public void setArena(Arena arena) {
        this.arena = arena;
    }

    public Robot getRobot() {
        return robot;
    }

    public void setRobot(Robot robot) {
        this.robot = robot;
    }

    public Graphics2D getGraphic() {
        return g;
    }

    public void setGraphic(Graphics2D g) {
        this.g = g;
    }
    
    private Drawer() {
        emptyPlottedCells = new Vector<Cell>();
    }
    
    public static Drawer getInstance() {
        return drawer;
    }
    
    private Point getGraphicCoordinate(Cell cell) {
        double x = X0 + cell.x * CELL_SIZE;
        double y = Y0 + cell.y * CELL_SIZE;
        return new Point(x, y);
    }
    
    private Point getGraphicRobotCoordinate() {
        Point p = getGraphicCoordinate(new Cell(robot.getX(), robot.getY()));
        p.x += CELL_SIZE;
        p.y += CELL_SIZE;
        return p;
    }
        
    private void drawCell(Cell cell, Color c) {
        Point point = getGraphicCoordinate(cell);
        g.setPaint(c);
        g.fill(new Rectangle2D.Double(point.x + CELL_ALIGN, point.y + CELL_ALIGN, CELL_SIZE - CELL_ALIGN * 2.0 + 1, CELL_SIZE - CELL_ALIGN * 2.0 + 1));
        g.setPaint(Color.LIGHT_GRAY);
        g.draw(new Rectangle2D.Double(point.x, point.y, CELL_SIZE, CELL_SIZE));        
    }
    
    private boolean drawed = false;
    
    public void drawArena() {
        if (!drawed)
            for (int i = 0; i < arena.WIDTH; i++) {
                for (int j = 0; j < arena.HEIGHT; j++) {                
                    drawCell(new Cell(i, j), Color.WHITE);
                }
            }
        
        drawed = true;
        
        Vector<Cell> emptyCells = arena.getEmptyCells();
        for (Cell c : emptyCells) {
            if (!isPlottedEmptyCell(c)) {
                drawCell(c, Color.RED);
                emptyPlottedCells.add(c);
            }
            
        }
        
        Vector<Cell> obstacleCells = arena.getObstacleCells();
        for (Cell c : obstacleCells) {
            drawCell(c, Color.BLACK);
        }
    }
    
    private boolean isPlottedEmptyCell(Cell cell) {
        boolean found = false;
        for (Cell c : emptyPlottedCells) {
            if (c.x == cell.x && c.y == cell.y)
                found = true;
        }
        return found;
    }
    
    public void drawRobot() {
        Point p = getGraphicCoordinate(new Cell(robot.getX(), robot.getY()));
        double delta = 3 * CELL_SIZE / 2.0 - ROBOT_SIZE / 2.0;
        p.x += delta;
        p.y += delta;
        g.setStroke(new BasicStroke(2));
        g.setPaint(Color.WHITE);
        g.fill(new Ellipse2D.Double(p.x, p.y, ROBOT_SIZE, ROBOT_SIZE));
        
        g.setPaint(Color.BLACK);
        g.draw(new Ellipse2D.Double(p.x, p.y, ROBOT_SIZE, ROBOT_SIZE));
        
        
        Point c = p;
        double e = 10;        
        c.x += ROBOT_SIZE / 2.0 - e / 2.0;
        c.y += ROBOT_SIZE / 2.0 - e / 2.0;
                
        
        
        switch (robot.getDirection()) {
            case Robot.UP:
                c.y -= 17;
                break;
            case Robot.RIGHT:
                c.x += 17;
                break;
            case Robot.DOWN:
                c.y += 17;
                break;
            case Robot.LEFT:
                c.x -= 17;
                break;
        }
        
        
        g.setPaint(Color.BLACK);
        g.fill(new Rectangle2D.Double(c.x, c.y, e, e));
    }
    
    public void draw() {
        drawArena();
        drawRobot();
    }
    
    public void update() {
        draw();
    }
}
